Ana içeriğe geç

Kontrol Akışı

Kontrol akışı bir kod parçasını belirli şartın sağlanıp sağlanmaması durumunda nerede ne şekilde çalışacağını veya bir kodun tekrarlı olarak çalışıp çalışmayacağını ifade ederken kullanmamızdır.

Kontrol akışı ifadeleri kodlama dilleri için hayati önem sağlamaktadır. Rust içerisinde yaygın kullanılan bir adet koşullu durumun ifadesi olan if ve 3 adet döngü bulunmaktadır.

If İfadesi

İlk olarak if ifadesi ile başlayabiliriz. If türkçeğe eğer olarak çevirilmektedir ve bir şartın gerçekleşmesi koşuluyla içerisindeki kodları çalıştırmaktadır. Bir örnek ile bu yapıya bakıcak olursak:

let sayi = 1;
if sayi > 0 {
println!("Evet doğru, tebrikler artık birinci sınıf talebesini RUST kullanarak ezebilirsin");
} else {
println!("Olsun be devamsızlıktan kalma, seneye öğrenirsin");
}

Kodumuzu incelediğimizde ilk olarak bir değişken tanımladığımızı görebiliriz. Bu değişken 1 değerine sahip unsigned integer bir değer olmaktadır. Sonrasında altında asıl önemli olan kısım if koşulu bizleri karşılamaktadır. Bu koşul if kelimesinden süslü parantezin başına kadar olan koşulun true veya false olmasını kontrol etmektedir. Eğer bu durum false ise içinde olan kod çalışmaz ancak true ise içinde olan kod çalışır. Bizim bu kod örneğimizde de sayı olarak isimlendirdiğimiz değişken 0 dan büyük olduğu için koşulumuz true döndürür ve iç kısmında bulunan println!() makrosu çalışır. Peki şart sağlanmasaydı yani false dönseydi ne olacaktı? O durumda da hemen altındaki else yapısı devreye girecek ve else kod blokları içerisindeki println!() makrosu çalışacaktı.

Daha önceden bir fonksiyonun birden fazla çıktısının olabileceğini söylemiştik hadi if ile birleştirerek bu olayı örneklendirelim. Fonksiyonumuz içerisine girilen sayı 10'dan büyükse Büyüktür 10'dan küçükse Küçüktür çıktısı veren bir fonksiyon yazabiliriz.

fn buyuk_kucuk(deger:u64)-> String{
if deger > 10{
"büyüktür".to_string() // ";" yok
} else {
"küçüktür".to_string() // ";" yok
}
}
fn main() {
let durum:String = buyuk_kucuk(9);
println!("{}",durum); // küçüktür
let durum:String = buyuk_kucuk(11);
println!("{}",durum); // büyüktür
}

Yukarıda ifade edilen kodu inceleyerek nasıl bir şekilde fonksiyonlar ile akış elemanlarını kontrol ettiğimizi görüntüleyebilirsiniz.

Aynı zamanda Rust içerisinde de farklı şartları birbirine bağlayabiliriz. Bu işlemi else if yapısı ile kontrol etmekteyiz. aynı if gibi bu yapıda da iç parantezine koşul almaktadır. Bu yapı else yapısının kapsamadığı şartlardan birini oluşturmaktadır. Bu durumu göstermek için üst kısımda yazdığımız kodu biraz daha özelleştirebiliriz.

fn buyuk_kucuk_esit(deger:u64)-> String{
if deger > 10{
"büyüktür".to_string() // ";" yok
} else if deger < 10{
"küçüktür".to_string() // ";" yok
} else{
"eşittir".to_string() // ";" yok
}
}
fn main() {
let durum:String = buyuk_kucuk(9);
println!("{}",durum); // küçüktür
let durum:String = buyuk_kucuk(11);
println!("{}",durum); // büyüktür
let durum:String = buyuk_kucuk(10);
println!("{}",durum); // eşittir
}

Loop İfadesi

Looplar türkçeye döngüler olarak çevrilmektedir ve bir işlemi sonsuza kadar yapmaya yaramaktadır. İçlerine yazılan kod bloklarını sırasıyla biri durduruna kadar sonsuza kadar yazarlar.

loop {
println!("Başım dönüyoooo") // Sonsuza kadar bu mesajı yazdıracak
}

Bu döngü sonsuza kadar devam edecektir. Ancak istersek biz terminalde ctrl + c ifadesini kullanarak durdurabiliriz.

Bu loop değerlerini isimsiz de oluşturabileceğimiz gibi isimler ile de tanımlayabiliriz. Ancak bu isimleri verirken dikkat etmemiz gereken şey döngü isimlerinin başlarına kesme işareti ' koymaktır. Peki neden döngülere isim vermemiz bizim için önemli? Sizlere döngülerin sonsuz olduğunu ve birisi durdurmadıkça sonsuza kadar devam edeceğini söylemiştik, peki nasıl bu döngüyü durduracağız? İşte bu döngüleri durdurmak için break methodumuz bulunmakta. Bu methodu döngünün içerisinde yalın olarak kullandığımızda en iç kısımında bulunan döngüyü kırmaktayız. Bu da bizi nested loop yani iç içe döngü kavramına getirmekte. Rust içerisinde istediğiniz kadar iç içe döngü oluşturmanız mümkün. Peki bir döngü zaten sonsuzken nasıl bu döngünün dışındaki döngü gerçekleşebilir? Hadi bir örnek ile bakalım.

loop {
println!("Merhaba");
loop {
println!("Nasılsın?");
}
}

Yukarda ifade edilen kodumuz bir iç içe döngü yani nested loop olmaktadır. Bu kodu çalıştırdığımızda şu şekilde bir çıktı ile karşılaşacağız.

Merhaba
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
...

Gördüğünüz gibi kodumuz çalışmaya üstten aşşağı başladığı için Merhaba ifadesini bir kez yazdırmış olsada altında bulunan döngüye girerek sonsuza kadar çıkamadı. Bu nedenle bir daha Merhaba yazdırmadı. Ancak bu durumdan kurtulmak için bir yöntemimiz olmakta. İşte bu yöntem break ! Break yapısı kullanarak döngüden direkt olarak çıkış yapabiliriz. Şimdi kodumuza break ilave ederek bu işlemi yeniden deneyelim.

loop {
println!("Merhaba");
loop {
println!("Nasılsın?");
break
}
}

İç loop içerisine break ibaresi ekledik. Şimdi çalıştırarak çıktıya bakalım:

Merhaba
Nasılsın?
Merhaba
Nasılsın?
Merhaba
Nasılsın?
...

Gördüğümüz gibi tamamen farklı bir sonuç oluştu. Kodumuzu şimdi satır satır inceleyelim. İlk olarak Merhaba yazdırarak başladık. Sonrasında iç loop'a girdik. Nasılsın? yazdırdık. Bir satır altına indiğimizde break anahtar kelimesine gelmekteyiz. Bu komut içinde bulunduğu loop'u kırarak dışarı çıkar. Sonrasında dış loop yeniden işleme girerek bizlere Merhaba yazdırır ve bu işlem sonsuza kadar devam eder.

Fark ettiğiniz gibi break yapısı sadece içerisinde bulunduğu en son döngüyü kırmaktadır. Peki biz iç kısımdan daha dış bir döngüyü kırmak istesek bu işlemi nasıl yapabiliriz? İşte burada da karşımıza loop'ları isimlendirmenin nasıl işimize yarayacağı çıkmaktadır. Eğer bir loop'a isim verirsek ve sonrasında break anahtar kelimesinin yanına bu ismi koyarsak ne kadar içerde olursak olalım herhangi bir loop'u kırabiliriz. Bu durumu kod içerisinde inceleyecek olursak:

'en_buyuk: loop{
println!("Merhaba");
'orta_derece: loop{
println!("Nasılsın");
'en_kucuk: loop{
break 'en_buyuk;
}
}
}

Yukarıda kullandığımız kod yapısını break'i yanlız bırakarak yazsaydık Merhaba ve Nasılsın ifadelerinin sonsuza kadar devam ettiğini görüntüleyecektik. Ancak bu şekilde yapmadığımız ve break 'en_buyuk yapısı ile hangi döngüyü kıracağımızı belirttiğimiz için terminale sadece alt kısımda ifade edilen çıktı oluştu ve sonsuza kadar gitmeden direkt olarak durdu.

Merhaba
Nasılsın

Ayrıca break yapısını if ile birleştirerek nasıl döngülerden belirli şartlar oluşunca çıkabileceğinizi görüntüleyebilirsiniz.

While Döngüsü

While döngüsü türkçeye bir ek olan ederken diye çevrilebilir. Yani bir cümle içerisinde kullanacak olursak "Eve gelince bana yardımederek masayı kurabilirsin" ifadesi örnek verebiliriz. Her nasıl bu cümlede yardım etme işi eve gelince şartı ile birleştiyse while döngüleri de belirli bir şartın true olduğu her an çalışmakta olup false olduğu anda çalışmayı bırakıyordur.

Bu duruma örnek vermek için 10'a kadar sayan bir program yazabiliriz.

let mut sayi = 0;
while sayi < 10{
println!("Sayımız: {}", sayi);
sayi = sayi + 1;
}

Bu şekilde yazdığımız kodu çalıştırınca while döngüsünün yanında bulunan şart false olana kadar çalıştığını görebiliriz.

Sayımız: 0
Sayımız: 1
Sayımız: 2
Sayımız: 3
Sayımız: 4
Sayımız: 5
Sayımız: 6
Sayımız: 7
Sayımız: 8
Sayımız: 9

Yukarıdaki kod çıktısında da görüntüleyebileceğimiz üzere sayi değerimiz sürekli artarken 10'a eşit olduğu anda şart sağlanmamış ve döngü kırılarak bitmiştir.

Eğer kodumuzun 10'u da içermesini istiyorsak < yerine <= ibaresini de kullanabiliriz.

Aynı zamanda while loop'una özel olmadan her loop'da çalışan farklı bir değeri de yazdığımız kodda örnekleyebiliriz. Bu değer ise continue olmakta. Diyelim ki 10'a kadar sayılarımızı yazdırdık ancak 7 değeri bize uğursuz geldi canımız istemedi ve döngüden çıkarmak istedik. İşte tam bu anda continue yapısını kullanabiliriz. continue yapısı çalıştığı anda kodumuz sonrasında bulunan işlemleri yapmadan yeniden çalışır ki bu bizim durumumuzda bir sayı atlaması anlamına gelmekedir. Hadi kodumuzu if ve continue ifadeleri ile 7'yi atlayan bir hale getirelim.

let mut sayi = 0;
while sayi < 10{
if sayi == 7{
sayi += 1;
continue;
}else{
println!("Sayı: {}", sayi);
sayi = sayi + 1
}
}

Kodumuzu çalıştırdığımızda görüntüleyebileceğiniz üzere 7 sayısı olmadan tüm çıktılar sorunsuz bir şekilde ekrana gelmektedir.

Sayı: 0
Sayı: 1
Sayı: 2
Sayı: 3
Sayı: 4
Sayı: 5
Sayı: 6
Sayı: 8
Sayı: 9

For Döngüsü

For döngüleri belirli bir koleksiyondaki elementler için bir işlemi tekarlamanın mükemmel bir yoludur. Örneğin bir vektör!

Hadi bir örnek yapalım. Diyelim ki bir vektörümüz var ve bu vekörün içerinde 1'den 10'a kadar sayılar var. Bizde bu sayıları yazdırmak istiyoruz. Bu işlem için alt kısımda bulunduğu gibi bir döngü yazmamız gerekmektedir.

let sayilar: Vec<i8> = (0..10).collect();
for sayi in sayilar{
println!("Sayı: {}", sayi);
}

Sırasıyla kodumuza bakıcak olursak ilk olarak [0,10) aralığında bir vektör oluşurup bu vektöre sayilar adını vermişiz. Sonrasında for döngüsü karşımıza çıkmış. Bu döngüyü "sayilar vektörünün içerisindeki(in) her bir değeri sırasıyla sayi değişkenine eşitle ve sonrasında ekrana yazdır" şeklinde türkçeleştirebiliriz. Kodumuzu çalıştırırsak alt kısımdaki gibi bir sonuç çıkacağını görüntüleyebiliriz.

Sayılar: 0
Sayılar: 1
Sayılar: 2
Sayılar: 3
Sayılar: 4
Sayılar: 5
Sayılar: 6
Sayılar: 7
Sayılar: 8
Sayılar: 9

Aynı zamanda vektörü for döngüsünde in ifadesinden sonra for sayi in (1..10){...} şeklinde tanımlayabiliriz.